﻿using Buildalyzer;
using Buildalyzer.Workspaces;
using LibGit2Sharp;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

namespace CodeCity.K8S.Service.BuildImage
{
    public class BuildImageHelper
    {
        string GitRootFolder;
        string GitPullUser;
        string GitPullPwd;
        string access_token;
        const string repo = "city_code";
        string owner;

        public BuildImageHelper(string token) {
            
            GitRootFolder = Environment.GetEnvironmentVariable("Git_Root_Folder");

            if (string.IsNullOrEmpty(GitRootFolder))
                GitRootFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "GitRoot");

            GitPullUser = Environment.GetEnvironmentVariable("Git_Pull_User") ?? "liuqingatchina";
            GitPullPwd = Environment.GetEnvironmentVariable("Git_Pull_Pwd");

            this.access_token = token;
        }
        

        async Task<T> GetDataAsync<T>(string url)
        {

            using (var httpClient = new HttpClient(new HttpClientHandler
            {
                UseCookies = false
            })
            { Timeout = new TimeSpan(0, 0, 30) })
            {
                httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                httpClient.DefaultRequestHeaders.AcceptCharset.Add(new StringWithQualityHeaderValue("utf-8"));
                //HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url);
                var respond = await httpClient.GetAsync(url);
                if (!respond.IsSuccessStatusCode) {
                    throw new Exception("请求接口失败");
                }
                var json = await respond.Content.ReadAsStringAsync();

                return JsonSerializer.Deserialize<T>(json);
            }


        }

        async Task<MaYunUserInfo> GetUser() {
            var url = $"https://gitee.com/api/v5/user?access_token={this.access_token}";
            var result = await this.GetDataAsync<MaYunUserInfo>(url);
            return result;
        }


        private string ExecuteCmd(string command, string args,string workDir = null)
        {
            Console.WriteLine(workDir);
            using (var pro = new Process())
            {
                pro.StartInfo.FileName = "docker";
                pro.StartInfo.Arguments = args;

                pro.StartInfo.CreateNoWindow = true;         // 不创建新窗口    
                pro.StartInfo.UseShellExecute = false;       //不启用shell启动进程  
                pro.StartInfo.RedirectStandardInput = true;  // 重定向输入    
                pro.StartInfo.RedirectStandardOutput = true; // 重定向标准输出    
                pro.StartInfo.RedirectStandardError = false; //重定向标准错误
                                                             // 重定向错误输出  
                if (workDir != null)
                    pro.StartInfo.WorkingDirectory = workDir;  //定义执行的路径 

                pro.Start();


                pro.StandardInput.WriteLine(command); //向cmd中输入命令

                pro.StandardInput.AutoFlush = true;


                //pro.StandardInput.WriteLine("exit");  //退出


                string outRead = pro.StandardOutput.ReadToEnd();

                Console.WriteLine(outRead);
                pro.WaitForExit(); //等待命令执行完成后退出

                pro.Close(); //关闭窗口

                return outRead;
            }
        }

        public void DockerBuild(string projectFolder,string imageName)
        {
            ExecuteCmd("docker",$" build -t  {imageName} .", projectFolder);
        }


        public async Task InitUserAppSettings(string folder,string username,string pwd) {

            var appSetting = Path.Combine(folder, "Web", "appsettings.json");
            var json = await File.ReadAllTextAsync(appSetting);

            json = json.Replace("$CodeCityUserName$", username)
                .Replace("$CodeCityPassWord$", pwd)
                .Replace("$CodeCityPgSqlHost$", Environment.GetEnvironmentVariable("CodeCityPgSqlHost") ?? "172.19.23.25")
                .Replace("$CodeCityPgSqlPort$", Environment.GetEnvironmentVariable("CodeCityPgSqlPort") ?? "32769")
                .Replace("$CodeCitySvr$", Environment.GetEnvironmentVariable("CodeCitySvr") ?? $"http://gameserver-svc.codecity-game.svc.cluster.local/");

            File.WriteAllText(appSetting, json, Encoding.UTF8);


        }

        public async Task<string> GitClone()
        {
            try
            {
                var currentUser = await GetUser();
                owner = currentUser.login;
            }
            catch {
                throw new Exception("获取用户信息失败,请检查token");
            }

            var folder = Path.Combine(GitRootFolder, owner);

            if (Directory.Exists(folder))
            {
                try
                {
                    Directory.Delete(folder, true);
                }
                catch
                {
                    foreach (var item in Directory.GetFiles(folder, "*.*", SearchOption.AllDirectories))
                    {
                        if (File.GetAttributes(item).ToString().IndexOf("ReadOnly") != -1)
                            File.SetAttributes(item, FileAttributes.Normal);
                        File.Delete(item);
                    }
                    try
                    {
                        Directory.Delete(folder, true);
                    }
                    catch (Exception ex)
                    {
                        throw new Exception("清空项目文件失败");
                    }
                }
            }

            if (!Directory.Exists(folder))
                Directory.CreateDirectory(folder);

            Repository.Clone($"https://gitee.com/{owner}/{repo}.git", folder, new CloneOptions()
            {
                CredentialsProvider = (url, user, cred) => new UsernamePasswordCredentials { Username = GitPullUser, Password = GitPullPwd }
            });

            //var result = Repository.Clone($"https://{GitPullUser}:{GitPullPwd}@gitee.com/{CurrentUser}/{Repo}.git", folder);

            //Console.WriteLine(result);
            return folder;

            //await AddDev(currentUser.login);

        }




        public async Task<List<MenuItemDTO>> GetMenus(string projectFolder, string generateCodeAttributeName)
        {
            var result = new List<MenuItemDTO>();
            AnalyzerManager manager = new AnalyzerManager();
            ProjectAnalyzer analyzer = manager.GetProject(Path.Combine(projectFolder, "Web","CitySystem.WebHost.csproj"));
            const string controller = "Controller";
            var workspace = analyzer.GetWorkspace();
            var project = workspace.CurrentSolution.Projects.FirstOrDefault();
            var compilation = await project.GetCompilationAsync();

            foreach (var document in project.Documents)
            {
                var tree = await document.GetSyntaxTreeAsync();
                var semanticModel = compilation.GetSemanticModel(tree);
                foreach (var classDeclarationSyntax in tree.GetRoot().DescendantNodes().OfType<ClassDeclarationSyntax>())
                {
                    var currentClassSymbol = semanticModel.GetDeclaredSymbol(classDeclarationSyntax) as INamedTypeSymbol;

                    var methods = currentClassSymbol.GetMembers().Where(p =>
                       p.Kind == SymbolKind.Method
                       && !p.IsStatic && !p.IsAbstract
                        );

                    foreach (var method in methods)
                    {

                        var attr = method.GetAttributes().FirstOrDefault(c => generateCodeAttributeName.Equals(c.AttributeClass.Name) || (generateCodeAttributeName + "Attribute").Equals(c.AttributeClass.Name));
                        if (attr == null) continue;

                        var argTitle = attr.NamedArguments.FirstOrDefault(p => p.Key == "Title");
                        var argUrl = attr.NamedArguments.FirstOrDefault(p => p.Key == "Url");

                        string url;

                        if (argUrl.Key == null || argUrl.Value.Value == null)
                        {
                            url = currentClassSymbol.Name;
                            if (url.EndsWith(controller))
                                url = url.Substring(0, url.Length - controller.Length);
                            url = $"/{url}/{method.Name}";
                        }
                        else
                        {
                            url = argUrl.Value.Value.ToString();
                        }

                        result.Add(new MenuItemDTO
                        {
                            Title = argTitle.Key == null || argTitle.Value.Value == null ? "" : argTitle.Value.Value.ToString(),
                            Type = "GET",
                            Url = url
                        });
                    }

                }
            }
            return result;
        }
    }
}
